/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.edi.db.table;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edi.db.EdiDb;
import com.edi.db.type.NullableType;

public class TableEntity {
	private static final Log log = LogFactory.getLog(TableEntity.class);
	private List<RowEntity> rows;
	private Map<String, Object> filterMap;

	private Hashtable<String, FieldEntity> fieldEntitys;

	private String tableName;

	private int index;

	public TableEntity() {
		rows = new ArrayList<RowEntity>();
		fieldEntitys = new Hashtable<String, FieldEntity>();
		filterMap = new HashMap<String, Object>();
		index = -1;
	}

	public TableEntity(String tableName) {
		rows = new ArrayList<RowEntity>();
		fieldEntitys = new Hashtable<String, FieldEntity>();
		filterMap = new HashMap<String, Object>();
		index = -1;
		this.tableName = tableName;
	}

	public boolean hasNextRow() {
		return index < rows.size() - 1;
	}

	public RowEntity next() {
		if (hasNextRow()) {
			index++;
		}
		return rows.get(index);
	}

	public void first() {
		index = rows.size() == 0 ? -1 : 0;
	}

	public RowEntity getRow(int index) {
		return rows.get(index);
	}

	public RowEntity getRow() {
		return rows.get(this.index);
	}

	public void setPrimaryKey(String fieldName) {
		FieldEntity field = this.fieldEntitys.get(fieldName);
		field.setIdentify(true);
	}

	public List<String> getPrimarykey() {
		List<String> keys = new ArrayList<String>();
		Collection<FieldEntity> fields = fieldEntitys.values();
		Iterator<FieldEntity> fieldIter = fields.iterator();
		while (fieldIter.hasNext()) {
			FieldEntity field = fieldIter.next();
			if (field.isIdentify())
				keys.add(field.getFieldName());
		}

		return keys;
	}

	public void addRow(RowEntity row) {
		rows.add(row);
	}

	public RowEntity newRow() {
		return new RowEntity(this);
	}

	public void addField(FieldEntity fieldEntity) {
		this.fieldEntitys.put(fieldEntity.getFieldName(), fieldEntity);
	}

	public void addField(String fieldName, String fieldType, boolean isPrimary,
			int size) {
		FieldEntity field = new FieldEntity();
		field.setIdentify(isPrimary);
		field.setFieldName(fieldName);
		field.setFieldType(fieldType);
		field.setSize(size);
		this.fieldEntitys.put(fieldName, field);
	}

	public void addField(String fieldName, String fieldType, int size) {
		FieldEntity field = new FieldEntity();
		field.setFieldName(fieldName.toLowerCase());
		field.setFieldType(fieldType);
		field.setSize(size);
		this.fieldEntitys.put(fieldName.toLowerCase(), field);
	}

	public void addField(String fieldName, String fieldType, boolean isPrimary) {
		FieldEntity field = new FieldEntity();
		field.setFieldName(fieldName);
		field.setFieldType(fieldType);
		field.setIdentify(isPrimary);
		this.fieldEntitys.put(fieldName, field);
	}

	public void addField(String fieldName, String fieldType) {
		FieldEntity field = new FieldEntity();
		field.setFieldName(fieldName);
		field.setFieldType(fieldType);
		if (StringUtils.equals(fieldType, EdiDb.TYPE_STRING))
			field.setSize(200);
		this.fieldEntitys.put(fieldName, field);
	}

	public List<RowEntity> getRows() {
		return rows;
	}

	public String toString() {
		Iterator<RowEntity> it = rows.iterator();
		StringBuffer xml = new StringBuffer(
				"<?xml version=\"1.0\" encoding=\"utf-8\"?><data tablename ='"
						+ tableName + "'>");
		while (it.hasNext()) {
			RowEntity rowEntity = it.next();
			if (rowEntity == null)
				continue;
			Hashtable<String, ColumnCell> cellHash = rowEntity.getColumnCells();
			xml.append("<row>");
			if (cellHash != null) {
				Set<String> keySet = cellHash.keySet();
				Iterator<String> keyIt = keySet.iterator();
				while (keyIt.hasNext()) {
					String cellEntity = keyIt.next();
					ColumnCell columnCell = cellHash.get(cellEntity);
					xml.append("<cell fieldName ='").append(
							columnCell.getFieldName().toLowerCase()).append(
							"' fieldType ='").append(
							columnCell.getFieldType().getName()).append(
							"' fieldValue='")
							.append(columnCell.getFieldValue());
					if (columnCell.getFieldEntity() != null)
						xml.append("' isIdentify ='").append(
								columnCell.getFieldEntity().isIdentify()
										+ "' />");
					else
						xml.append("'/>");
				}
			}
			xml.append("</row>");
		}
		xml.append("</data>");
		return xml.toString();
	}

	public List getFieldNameList() {
		List<String> fieldNameist = new ArrayList<String>();

		Hashtable<String, FieldEntity> fields = this.getFieldEntitys();
		Set<String> fieldNames = fields.keySet();
		fieldNameist.addAll(fieldNames);

		return fieldNameist;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public Hashtable<String, FieldEntity> getFieldEntitys() {
		return fieldEntitys;
	}

	public NullableType getFieldType(String fieldName) {
		FieldEntity fieldEntity = fieldEntitys.get(fieldName);
		return fieldEntity == null ? null : fieldEntity.getFieldType();
	}

	public void setFieldEntity(Hashtable<String, FieldEntity> fieldEntity) {
		this.fieldEntitys = fieldEntity;
	}

	public void addFilter(String fieldName, Object fieldValue) {
		this.filterMap.put(fieldName.toLowerCase(), fieldValue);
	}

	public void clearFilters() {
		this.filterMap.clear();
	}

	/**
	 * 根据已设计的过滤条件进行过滤
	 * delete  过滤后删除
	 * @return
	 */
	public List<RowEntity> toFilter(boolean delete) {
		List<RowEntity> filterList = new ArrayList<RowEntity>();
		if (filterMap.size() == 0)
			return filterList;
		Iterator<RowEntity> it=rows.iterator();
		while(it.hasNext()){
			RowEntity row=it.next();
			Set<String> filterFields = filterMap.keySet();
			int matchSum = 0;
			for (String field : filterFields) {
				Object cellValue = filterMap.get(field);
				if (cellValue == null) {
					continue;
				}
				Object actCellValue = row.getCell(field).getFieldValue();
				boolean isEquals = false;
				if (actCellValue instanceof Date) {
					isEquals = DateUtils.isSameDay((Date) cellValue,
							(Date) actCellValue);
				} else
					isEquals = actCellValue.equals(cellValue);
				if (isEquals) {
					//当前行的字段值与过滤条件中的字段值匹配，则对字段匹配项加一
					matchSum++;
				}
				if (matchSum == filterMap.size()) { //进行到最后一个字段，并且匹配数与过滤数相同，说明本行记录符合过滤要求
					filterList.add(row);
					if (delete)
						it.remove();					//当所有条件都匹配之后 移除这条记录
					break;
				}
			}
		}
 

		return filterList;
	}
}
